package com.ruicar.afs.cloud.filecenter.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruicar.afs.cloud.common.core.uid.UidGenerator;
import com.ruicar.afs.cloud.common.core.util.Base64Util;
import com.ruicar.afs.cloud.common.data.lock.anno.Lock;
import com.ruicar.afs.cloud.filecenter.config.FileProperties;
import com.ruicar.afs.cloud.filecenter.entity.AfsFileChunkInfo;
import com.ruicar.afs.cloud.filecenter.entity.AfsFileInfo;
import com.ruicar.afs.cloud.filecenter.entity.AfsFileStore;
import com.ruicar.afs.cloud.filecenter.enums.ProcessStatus;
import com.ruicar.afs.cloud.filecenter.mapper.FileChunkInfoMapper;
import com.ruicar.afs.cloud.filecenter.mapper.FileStoreMapper;
import com.ruicar.afs.cloud.filecenter.service.IFileChunkService;
import com.ruicar.afs.cloud.filecenter.service.IFileInfoService;
import com.ruicar.afs.cloud.filecenter.service.IFileStoreService;
import com.ruicar.afs.cloud.filecenter.vo.FileStoreVo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.Date;


/**
 * FileStoreService
 * <p>Description: </p>
 *
 * @author Fzero
 * @version 1.0
 * @date create on 20191224 04:25:37
 * @since 1.0
 */
@Service
@Data
@Slf4j
@AllArgsConstructor
public class FileStoreService extends ServiceImpl<FileStoreMapper, AfsFileStore> implements IFileStoreService {
    private final IFileChunkService iFileChunkService;

    private final IFileInfoService fileInfoService;

    private final FileProperties fileProperties;

    private final FileChunkInfoMapper fileChunkInfoMapper;

    private final UidGenerator uidGenerator;

    /**
     * Store file file store vo
     * <p>Description: </p>
     * 上传文件入库处理
     *
     * @param file file
     * @return the file store vo
     */
    @SneakyThrows
    @Override
    @Lock(keys = "#md5",keyConstant = ":md5-for-file")
    @Transactional(rollbackFor = Exception.class)
    public FileStoreVo storeFile(MultipartFile file, String md5, int chunkNumber, int currentChunkSize, int totalChunks, long totalSize, String fileGuid){
        AfsFileStore afsFileStore =  this.baseMapper.selectOne(Wrappers.<AfsFileStore>lambdaQuery().eq(AfsFileStore::getChunkedId,md5));
        if(afsFileStore ==null){
            afsFileStore = new AfsFileStore();
            afsFileStore.setFileSize(totalSize);
            afsFileStore.setTempSize(currentChunkSize);
            afsFileStore.setChunkedId(md5);
            String day = DateUtil.formatDate(new Date());
            afsFileStore.setFilePath(day+File.separator+UUID.fastUUID().toString().replaceAll("-","")+".store");
            afsFileStore.setThumbnailPath(day+File.separator+UUID.fastUUID().toString().replaceAll("-","")+"_thumbnail.thumbnail");
            afsFileStore.setMd5Value(md5);
            afsFileStore.setProcessStatus(ProcessStatus.UPLOADING.getCode());
            this.baseMapper.insert(afsFileStore);
        }else{
            afsFileStore.setTempSize(afsFileStore.getTempSize()+currentChunkSize);
            this.baseMapper.updateById(afsFileStore);
        }
        AfsFileInfo afsFileInfo = this.fileInfoService.getOne(Wrappers.<AfsFileInfo>lambdaQuery().eq(AfsFileInfo::getGuid,fileGuid));
        if(afsFileInfo ==null) {
            afsFileInfo = new AfsFileInfo();
            afsFileInfo.setAccessKey(UUID.fastUUID().toString().replaceAll("-", ""));
            afsFileInfo.setFileName(file.getOriginalFilename());
            afsFileInfo.setFileType(FileUtil.extName(file.getOriginalFilename()));
            afsFileInfo.setFileMime(FileUtil.getMimeType(file.getOriginalFilename()));
            afsFileInfo.setFileMd5(md5);
            afsFileInfo.setGuid(fileGuid);
            fileInfoService.save(afsFileInfo);
        }
        AfsFileChunkInfo afsFileChunkInfo = iFileChunkService.getOne(Wrappers.<AfsFileChunkInfo>lambdaQuery().eq(AfsFileChunkInfo::getChunkedId,md5).eq(AfsFileChunkInfo::getChunkedIndex,chunkNumber));
        if(afsFileChunkInfo ==null){
            afsFileChunkInfo = new AfsFileChunkInfo();
            afsFileChunkInfo.setChunkedId(md5);
            afsFileChunkInfo.setChunkedIndex(chunkNumber);
            afsFileChunkInfo.setChunkedFilePath(md5+"_"+UUID.fastUUID().toString().replaceAll("-",""));
            if(fileProperties.isUseDb()){
                afsFileChunkInfo.setId(uidGenerator.getUID());
                afsFileChunkInfo.setChunkedValue(file.getBytes());
                fileChunkInfoMapper.addChunkInfo(afsFileChunkInfo);
            }else{
                iFileChunkService.save(afsFileChunkInfo);
                file.transferTo(new File(fileProperties.getTempDir()+File.separator+ afsFileChunkInfo.getChunkedFilePath()));
            }
        }
        return FileStoreVo.builder().build();
    }
}
